#include "Logger.h"

#include <QString>

#include <iostream>
#include <string>

#include "AutoLock.h"

#define LOGGER_LOCK	AutoLock logger_auto_lock_variable(&lock);

/*
	Logger
*/

/*	private	*/

Lockable Logger::lock;
bool Logger::color = true;

#ifdef DEBUG
Logger::Level Logger::level = Debug;
#else
Logger::Level Logger::level = Info;
#endif	/* DEBUG */

int Logger::levelToInt(Level l) {
	switch(l) {
	case Debug:
		return 5;
	case Info:
		return 4;
	case Warning:
		return 3;
	case Error:
		return 2;
	case Fatal:
		return 1;
	default:
		return 0;
	}
}

bool Logger::checkLevel(Level l) {
	return levelToInt(level) >= levelToInt(l);
}

std::string doIndent(int indent) {
	std::string result = "";
	for (int i = 0; i < indent; i++) {
		result += LOGGER_INDENT_SPACE;
	}
	return result;
}

void Logger::doDebug(const char* message, int indent) {
	LOGGER_LOCK
	std::cerr << (color ? "\033[01;32mDEBUG :\033[01;00m " : "DEBUG : ")
		<< doIndent(indent) << message << "\n";
	std::cerr.flush();
}

void Logger::doInfo(const char* message, int indent) {
	LOGGER_LOCK
	std::cerr << (color ? "\033[01;34mINFO  :\033[01;00m " : "INFO  : ")
		<< doIndent(indent) << message << "\n";
	std::cerr.flush();
}

void Logger::doWarning(const char* message, int indent) {
	LOGGER_LOCK
	std::cerr << (color ? "\033[01;33mWARNING:\033[01;00m " : "WARNING: ")
		<< doIndent(indent) << message << "\n";
	std::cerr.flush();
}

void Logger::doError(const char* message, int indent) {
	LOGGER_LOCK
	std::cerr << (color ? "\033[01;31mERROR :\033[01;00m " : "ERROR : ")
		<< doIndent(indent) << message << "\n";
	std::cerr.flush();
}

void Logger::doFatal(const char* message, int indent) {
	LOGGER_LOCK
	std::cerr << (color ? "\033[01;35mFATAL :\033[01;00m " : "FATAL : ")
		<< doIndent(indent) << message << "\n";
	std::cerr.flush();
}

/*	public	*/

void Logger::setLevel(Level level) {
	LOGGER_LOCK
	Logger::level = level;
}

void Logger::setColor(bool color) {
	LOGGER_LOCK
	Logger::color = color;
}


/* debug */
void Logger::debug(const QString& message, int indent) {
	if (checkLevel(Debug)) {
		doDebug(message.toLatin1().data(), indent);
	}
}

void Logger::debug(const char* message, int indent) {
	if (checkLevel(Debug)) {
		doDebug(message, indent);
	}
}


/* info */
void Logger::info(const QString& message, int indent) {
	if (checkLevel(Info)) {
		doInfo(message.toLatin1().data(), indent);
	}
}

void Logger::info(const char* message, int indent) {
	if (checkLevel(Info)) {
		doInfo(message, indent);
	}
}


/* warning */
void Logger::warning(const QString& message, int indent) {
	if (checkLevel(Warning)) {
		doWarning(message.toLatin1().data(), indent);
	}
}

void Logger::warning(const char* message, int indent) {
	if (checkLevel(Warning)) {
		doWarning(message, indent);
	}
}


/* error */
void Logger::error(const QString& message, int indent) {
	if (checkLevel(Error)) {
		doError(message.toLatin1().data(), indent);
	}
}

void Logger::error(const char* message, int indent) {
	if (checkLevel(Error)) {
		doError(message, indent);
	}
}


/* fatal */
void Logger::fatal(const QString& message, int indent) {
	if (checkLevel(Fatal)) {
		doFatal(message.toLatin1().data(), indent);
	}
}

void Logger::fatal(const char* message, int indent) {
	if (checkLevel(Fatal)) {
		doFatal(message, indent);
	}
}


